/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.notepad;

import java.util.List;

import android.app.Dialog;
import android.app.ListActivity;
import android.content.ComponentName;
import android.content.ContentUris;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.BaseColumns;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

import com.example.android.notepad.NotePad.NoteColumns;

import de.fuberlin.replication.application.android.communication.CommunicationType;
import de.fuberlin.replication.application.android.communication.bluetooth.BluetoothCommunicationType;
import de.fuberlin.replication.application.android.communication.wifi.WiFiCommunicationType;
import de.fuberlin.replication.application.android.os.SynchronizationTask;

/**
 * Displays a list of notes. Will display notes from the {@link Uri} provided in the intent if there is one, otherwise
 * defaults to displaying the contents of the {@link NoteProvider}
 */
public class NotesList extends ListActivity {
	private static final String TAG = "NotesList";

	/**
	 * The columns we are interested in from the database
	 */
	private static final String[] PROJECTION = new String[] {
			BaseColumns._ID, // 0
			NoteColumns.TITLE, // 1
	};

	/** The index of the title column */
	private static final int COLUMN_INDEX_TITLE = 1;

	private NotePadSynchronizable synchronizable;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		/**
		 * The library needs a implementation of the Synchronizable interface, which is instantiated here.
		 */
		synchronizable = (NotePadSynchronizable) getLastNonConfigurationInstance();

		if (synchronizable == null) {
			synchronizable = new NotePadSynchronizable(this);

			List<CommunicationType> types = synchronizable.getCommunicationManager().getTypes();
			types.add(new BluetoothCommunicationType());
			types.add(new WiFiCommunicationType());
		}

		synchronizable.getCommunicationManager().setActivity(this);

		setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);

		// If no data was given in the intent (because we were started
		// as a MAIN activity), then use our default content provider.
		Intent intent = getIntent();
		if (intent.getData() == null)
			intent.setData(NoteColumns.CONTENT_URI);

		// Inform the list we provide context menus for items
		getListView().setOnCreateContextMenuListener(this);

		// Perform a managed query. The Activity will handle closing and requerying the cursor
		// when needed.
		Cursor cursor = managedQuery(getIntent().getData(), PROJECTION, null, null,
										NoteColumns.DEFAULT_SORT_ORDER);

		// Used to map notes entries from the database to views
		SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.noteslist_item, cursor,
				new String[] {NoteColumns.TITLE}, new int[] {android.R.id.text1});
		setListAdapter(adapter);
	}

	@Override
	public Object onRetainNonConfigurationInstance() {
		NotePadSynchronizable retainedSynchronizable = synchronizable;

		return retainedSynchronizable;
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();

		synchronizable.getCommunicationManager().setActivity(null);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate menu from XML resource
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.list_options_menu, menu);

		// Generate any additional actions that can be performed on the
		// overall list. In a normal install, there are no additional
		// actions found here, but this allows other applications to extend
		// our menu with their own actions.
		Intent intent = new Intent(null, getIntent().getData());
		intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
		menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
				new ComponentName(this, NotesList.class), null, intent, 0, null);

		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
			case R.id.menu_add:
				// Launch activity to insert a new item
				startActivity(new Intent(Intent.ACTION_INSERT, getIntent().getData()));
				return true;
				/**  */
			case R.id.menu_synchronize:
				SynchronizationTask task = new SynchronizationTask(synchronizable);
				task.execute();

				return true;
			default:
				return super.onOptionsItemSelected(item);
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		synchronizable.getCommunicationManager().onActivityResult(requestCode, resultCode, data);
	}

	@Override
	protected Dialog onCreateDialog(int id, Bundle args) {
		return synchronizable.getCommunicationManager().onCreateDialog(id, args);
	}

	@Override
	protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
		synchronizable.getCommunicationManager().onPrepareDialog(id, dialog, args);
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {
		AdapterView.AdapterContextMenuInfo info;
		try {
			info = (AdapterView.AdapterContextMenuInfo) menuInfo;
		} catch (ClassCastException e) {
			Log.e(TAG, "bad menuInfo", e);
			return;
		}

		Cursor cursor = (Cursor) getListAdapter().getItem(info.position);
		if (cursor == null)
			// For some reason the requested item isn't available, do nothing
			return;

		// Inflate menu from XML resource
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.list_context_menu, menu);

		// Set the context menu header
		menu.setHeaderTitle(cursor.getString(COLUMN_INDEX_TITLE));

		// Append to the
		// menu items for any other activities that can do stuff with it
		// as well. This does a query on the system for any activities that
		// implement the ALTERNATIVE_ACTION for our data, adding a menu item
		// for each one that is found.
		Intent intent = new Intent(null, Uri.withAppendedPath(getIntent().getData(),
										Integer.toString((int) info.id)));
		intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
		menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
				new ComponentName(this, NotesList.class), null, intent, 0, null);
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		AdapterView.AdapterContextMenuInfo info;
		try {
			info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
		} catch (ClassCastException e) {
			Log.e(TAG, "bad menuInfo", e);
			return false;
		}

		Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), info.id);

		switch (item.getItemId()) {
			case R.id.context_open:
				// Launch activity to view/edit the currently selected item
				startActivity(new Intent(Intent.ACTION_EDIT, noteUri));
				return true;
			case R.id.context_delete:
				// Delete the note that the context menu is for
				getContentResolver().delete(noteUri, null, null);
				return true;
			default:
				return super.onContextItemSelected(item);
		}
	}

	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), id);

		String action = getIntent().getAction();
		if (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action))
			// The caller is waiting for us to return a note selected by
			// the user. The have clicked on one, so return it now.
			setResult(RESULT_OK, new Intent().setData(noteUri));
		else
			// Launch activity to view/edit the currently selected item
			startActivity(new Intent(Intent.ACTION_EDIT, noteUri));
	}
}